using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication1
{
    public class SpawnPoints : Object
    {
        public enum Characters {SURVIVOR_SPAWN, SURVIVOR_RESPAWN, INFECTED_REGULAR, INFECTED_HUNTER, INFECTED_BOOMER, INFECTED_SMOKER, INFECTED_TANK, INFECTED_WITCH, INFECTED_RANDOM, MAX};
        Point location = new Point(0, 0);
        public Point Location
        {
            get { return location; }
            set { location = value; }
        }
        int type = (int)Characters.SURVIVOR_SPAWN;
        public int Type
        {
            get { return type; }
            set { type = value; }
        }
        int numberOfSpawns = 1;
        public int NumberOfSpawns
        {
            get { return numberOfSpawns; }
            set { numberOfSpawns = value; }
        }
        int timeBetweenSpawning = 1000;
        public int TimeBetweenSpanwing
        {
            get { return timeBetweenSpawning; }
            set { timeBetweenSpawning = value; }
        }
        public SpawnPoints(Point _location, int _type, int _numberOfSpawns, int _timeBetweenSpawns)
        {
            location = _location;
            type = _type;
            numberOfSpawns = _numberOfSpawns;
            timeBetweenSpawning = _timeBetweenSpawns;
        }
        public override string ToString()
        {
            if (type == (int)Characters.INFECTED_BOOMER)
                return "Spawn Point: Boomer";
            if (type == (int)Characters.INFECTED_HUNTER)
                return "Spawn Point: Hunter";
            if (type == (int)Characters.INFECTED_REGULAR)
                return "Spawn Point: Regular Infected";
            if (type == (int)Characters.INFECTED_SMOKER)
                return "Spawn Point: Smoker";
            if (type == (int)Characters.INFECTED_TANK)
                return "Spawn Point: Tank";
            if (type == (int)Characters.INFECTED_WITCH)
                return "Spawn Point: Witch";
            if (type == (int)Characters.INFECTED_RANDOM)
                return "Spawn Point: Random Infected";
            if (type == (int)Characters.SURVIVOR_SPAWN)
                return "Spawn Point: Survivor";
            if (type == (int)Characters.SURVIVOR_RESPAWN)
                return "Respawn Point: Survivor";
            return "Unknown";
        }
    }
    public class Tile : Object
    {
        public enum CollisionTypes { NO_COLLISION, COLLISION, LADDER, DOOR };

        LoadedBitmap currentBitmap;
        public LoadedBitmap CurrentBitmap
        {
            get { return currentBitmap; }
            set { currentBitmap = value; }
        }

        Point tileLocation;
        public Point TileLocation
        {
            get { return tileLocation; }
            set { tileLocation = value; }
        }

        int collision;
        public int Collision
        {
            get { return collision; }
            set { collision = value; }
        }

        Point doorTo;
        public Point DoorTo
        {
            get { return doorTo; }
            set { doorTo = value; }
        }

        public Tile(LoadedBitmap _currentBitmap, Point _tileLocation, int _collision)
        {
            CurrentBitmap = _currentBitmap;
            TileLocation = _tileLocation;
            Collision = _collision;
            DoorTo = new Point(-1, -1);
        }

        public bool IsEqual(Tile _tile)
        {
            if (_tile == null)
                return false;
            if (_tile.TileLocation == TileLocation && ((CurrentBitmap == _tile.CurrentBitmap) || (_tile.CurrentBitmap != null && _tile.CurrentBitmap.IsEqual(CurrentBitmap))))
                return true;
            return false;
        }
    }

    public class LoadedBitmap : Object
    {
        Bitmap bitmap;
        int bitmapIndex;
        String filename = "";
        public LoadedBitmap(String _filename)
        {
            bitmap = new Bitmap(_filename);
            bitmap.MakeTransparent(Color.FromArgb(255, 255, 255));
            bitmapIndex = SGD.ManagedTextureManager.Instance.LoadTexture(_filename, Color.FromArgb(255, 255, 255, 255).ToArgb());
            filename = _filename;
        }
        public Bitmap GetBitmap()
        {
            return bitmap;
        }
        public int GetBitmapIndex()
        {
            return bitmapIndex;
        }
        public String GetFilename()
        {
            return filename;
        }
        public bool IsEqual(LoadedBitmap _bitmap)
        {
            if (_bitmap == null)
                return false;
            if (_bitmap.GetBitmapIndex() == GetBitmapIndex())
                return true;
            return false;
        }
        public override string ToString()
        {
            return filename.Substring(filename.LastIndexOf('\\') + 1);
        }
    }

    public class Layer : Object
    {
        List<List<Tile>> grid = new List<List<Tile>>();
        int layerNumber;
        int type;
        public Layer(int _layerNumber, int _type, int _width, int _height)
        {
            layerNumber = _layerNumber;
            type = _type;
            SetWidth(_width);
            SetHeight(_height);
        }
        public Tile GetElement(int _x, int _y)
        {
            if (_x < 0 || _y < 0 || _x >= grid.Count || _y >= grid[_x].Count)
                return null;
            return grid[_x][_y];
        }
        public void SetElement(int _x, int _y, LoadedBitmap _bitmap, Point _tileLocation, int _collisionType, Point _doorTo)
        {
            if (_x < 0 || _y < 0 || _x >= grid.Count || _y >= grid[_x].Count)
                return;
            grid[_x][_y].CurrentBitmap = _bitmap;
            grid[_x][_y].TileLocation = _tileLocation;
            grid[_x][_y].Collision = _collisionType;
            grid[_x][_y].DoorTo = _doorTo;
        }
        public void SetWidth(int _width)
        {
            while (grid.Count > _width)
                grid.RemoveAt(grid.Count - 1);
            while (grid.Count < _width)
            {
                grid.Add(new List<Tile>());
                for (int h = 0; h < grid.Count; h++)
                    grid[grid.Count - 1].Add(new Tile(null, new Point(0, 0), (int)Tile.CollisionTypes.NO_COLLISION));
            }
        }
        public void SetHeight(int _height)
        {
            for (int w = 0; w < grid.Count; w++)
            {
                while (grid[w].Count > _height)
                    grid[w].RemoveAt(grid[w].Count - 1);
                while (grid[w].Count < _height)
                    grid[w].Add(new Tile(null, new Point(0, 0), (int)Tile.CollisionTypes.NO_COLLISION));
            }
        }
        public override string ToString()
        {
            if(type == 1)
                return "Graphic Layer "+layerNumber;
            return "Collision Layer";
        }
        public int GetLayerType()
        {
            return type;
        }
        
    }

    public class Level
    {
        TileEditorForm parent;
        public int layerNumber = 1;
        Size tileSize = new Size(32, 32);
        Size boardSize = new Size(0, 0);
        public List<SpawnPoints> spawnPoints = new List<SpawnPoints>();
        public List<SpawnPoints> spawnPointsAvailable = new List<SpawnPoints>();
        public SpawnPoints spawnPointToAdd;
        public Point doorToAdd = new Point(-1, -1);
        //
        public Level(TileEditorForm _parent)
        {
            parent = _parent;
            parent.Button_RemoveTileset.Enabled = false;
            BoardWidth = 10;
            BoardHeight = 10;
            parent.List_Layers.Items.Add(new Layer(1, 0, boardSize.Width, boardSize.Height));
            parent.List_Layers.Items.Add(new Layer(layerNumber++, 1, boardSize.Width, boardSize.Height));
            parent.List_Layers.SelectedIndex = 1;
            //
            for(int i = 0; i < (int)SpawnPoints.Characters.MAX; i++){
                spawnPointsAvailable.Add(new SpawnPoints(new Point(0, 0), i, 1, 1000));
            }
        }
        public int TileWidth
        {
            get { return tileSize.Width; }
            set
            {
                if (value < 1)
                    return;
                tileSize.Width = value;
                parent.TileWidth.Value = value;
            }
        }
        public int TileHeight
        {
            get { return tileSize.Height; }
            set
            {
                if (value < 1)
                    return;
                tileSize.Height = value;
                parent.TileHeight.Value = value;
            }
        }
        public int BoardWidth
        {
            get { return boardSize.Width; }
            set
            {
                if (boardSize.Width == value || value < 1)
                    return;
                for (int i = 0; i < parent.List_Layers.Items.Count; i++)
                {
                    (parent.List_Layers.Items[i] as Layer).SetWidth(value);
                }
                boardSize.Width = value;
                parent.BoardWidth.Value = value;
            }
        }
        public int BoardHeight
        {
            get { return boardSize.Height; }
            set
            {
                if (boardSize.Height == value || value < 1)
                    return;
                for (int i = 0; i < parent.List_Layers.Items.Count; i++)
                {
                    (parent.List_Layers.Items[i] as Layer).SetHeight(value);
                }
                boardSize.Height = value;
                parent.BoardHeight.Value = value;
            }
        }
        public void AddLayer()
        {
            parent.List_Layers.Items.Add(new Layer(layerNumber++, 1, boardSize.Width, boardSize.Height));
        }
        public void RemoveLayer()
        {
            int index = parent.List_Layers.SelectedIndex;
            if ((parent.List_Layers.Items[index] as Layer).GetLayerType() == 0)
            {
                MessageBox.Show("Cannot remove Collision Layer. Each level needs a collision layer to function.", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            parent.List_Layers.Items.RemoveAt(index);
            if (parent.List_Layers.Items.Count > 0)
                parent.List_Layers.SelectedIndex = parent.List_Layers.Items.Count - 1;
            if (parent.List_Layers.Items.Count > index)
                parent.List_Layers.SelectedIndex = index;
        }
        public void AddBitmap()
        {
            OpenFileDialog dlg = new OpenFileDialog();
            if (DialogResult.OK == dlg.ShowDialog() && dlg.CheckFileExists)
            {
                for (int i = 0; i < parent.List_Tilesets.Items.Count; i++)
                {
                    if ((parent.List_Tilesets.Items[i] as LoadedBitmap).GetFilename() == dlg.FileName)
                    {
                        MessageBox.Show("An image with that filename has already been loaded. Remove the other file first.", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        return;
                    }
                }
                parent.List_Tilesets.Items.Add(new LoadedBitmap(dlg.FileName));
                parent.List_Tilesets.SelectedIndex = parent.List_Tilesets.Items.Count - 1;
                parent.Button_RemoveTileset.Enabled = true;
            }
        }
        public void RemoveBitmap()
        {
            if (parent.List_Tilesets.Items.Count > 0)
            {
                int index = parent.List_Tilesets.SelectedIndex;
                parent.List_Tilesets.Items.RemoveAt(parent.List_Tilesets.SelectedIndex);
                if (parent.List_Tilesets.Items.Count > 0)
                    parent.List_Tilesets.SelectedIndex = parent.List_Tilesets.Items.Count - 1;
                if (parent.List_Tilesets.Items.Count > index)
                    parent.List_Tilesets.SelectedIndex = index;
            }
        }
        public void ResetLayerNumber()
        {
            layerNumber = 1;
        }
        public void SwapLayers(int _indexOne, int _indexTwo)
        {
            if (_indexOne < 0 || _indexOne >= parent.List_Layers.Items.Count || _indexTwo < 0 || _indexTwo >= parent.List_Layers.Items.Count)
                return;
            Layer tempLayer = parent.List_Layers.Items[_indexOne] as Layer;
            parent.List_Layers.Items[_indexOne] = parent.List_Layers.Items[_indexTwo] as Layer;
            parent.List_Layers.Items[_indexTwo] = tempLayer;
        }
    }

}